﻿using System;
using System.Collections.ObjectModel;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using VioletDevelopmentLaboratory.Net.Data;
using VioletDevelopmentLaboratory.Net.Web.Configuration;

namespace VioletDevelopmentLaboratory.Net.Web.Component
{
	public enum TagAddResult { Success, Already }
	public enum TagRemoveResult { Success, Unknown }
	public enum TagRemoveAllResult { Success, Failure }

	public class Tag
	{
		public Tag(String name, Int32 count)
		{
			this.name = name;
			this.count = count;
		}

		private String name;
		public String Name { get { return this.name; } }

		private Int32 count;
		public Int32 Count { get { return this.count; } }

		public static TagAddResult Add(String componentID, String relationID, String name)
		{
			if (componentID == null)
				throw new ArgumentNullException("componentID");

			if (relationID == null)
				throw new ArgumentNullException("relationID");

			if (name == null)
				throw new ArgumentNullException("name");

			if (String.IsNullOrEmpty(componentID))
				throw new ArgumentOutOfRangeException("componentID");

			if (String.IsNullOrEmpty(relationID))
				throw new ArgumentOutOfRangeException("relationID");

			if (String.IsNullOrEmpty(name))
				throw new ArgumentOutOfRangeException("name");

			if (!VUtility.IsGuid(relationID))
				throw new FormatException("relationID must Guid.");

			Object returnValue = null;

			SqlClientAgent.ExecuteNonQuery(
				ConfigurationManager.ConnectionStrings[VWebConfigurationReader.ConnectionStringName].ConnectionString,
				CommandType.StoredProcedure,
				"VWeb_Tag_Create",
				out returnValue,
				new SqlParameter("@ApplicationName", VWebConfigurationReader.ApplicationName),
				new SqlParameter("@ComponentID", componentID),
				new SqlParameter("@RelationID", relationID),
				new SqlParameter("@TagName", name)				
			);

			switch ((Int32)returnValue)
			{
				case 0:
					return TagAddResult.Success;
				default:
					return TagAddResult.Already;
			}
		}

		public static TagRemoveResult Remove(String componentID, String relationID, String name)
		{
			if (componentID == null)
				throw new ArgumentNullException("componentID");

			if (relationID == null)
				throw new ArgumentNullException("relationID");

			if (name == null)
				throw new ArgumentNullException("name");

			if (String.IsNullOrEmpty(componentID))
				throw new ArgumentOutOfRangeException("componentID");

			if (String.IsNullOrEmpty(relationID))
				throw new ArgumentOutOfRangeException("relationID");

			if (String.IsNullOrEmpty(name))
				throw new ArgumentOutOfRangeException("name");

			if (!VUtility.IsGuid(relationID))
				throw new FormatException("relationID must Guid.");

			Object returnValue = null;

			SqlClientAgent.ExecuteNonQuery(
				ConfigurationManager.ConnectionStrings[VWebConfigurationReader.ConnectionStringName].ConnectionString,
				CommandType.StoredProcedure,
				"VWeb_Tag_Delete",
				out returnValue,
				new SqlParameter("@ApplicationName", VWebConfigurationReader.ApplicationName),
				new SqlParameter("@ComponentID", componentID),
				new SqlParameter("@RelationID", relationID),
				new SqlParameter("@TagName", name)
			);

			switch ((Int32)returnValue)
			{
				case 0:
					return TagRemoveResult.Success;
				default:
					return TagRemoveResult.Unknown;
			}
		}

		public static TagRemoveAllResult RemoveAll()
		{
			Object returnValue = null;

			SqlClientAgent.ExecuteNonQuery(
				ConfigurationManager.ConnectionStrings[VWebConfigurationReader.ConnectionStringName].ConnectionString,
				CommandType.StoredProcedure,
				"VWeb_Tag_DeleteAllByApplicationName",
				out returnValue,
				new SqlParameter("@ApplicationName", VWebConfigurationReader.ApplicationName)
			);

			switch ((Int32)returnValue)
			{
				case 0:
					return TagRemoveAllResult.Success;
				default:
					return TagRemoveAllResult.Failure;
			}
		}

		public static TagRemoveAllResult RemoveAll(String componentID)
		{
			if (componentID == null)
				throw new ArgumentNullException("componentID");

			if (String.IsNullOrEmpty(componentID))
				throw new ArgumentOutOfRangeException("componentID");

			Object returnValue = null;

			SqlClientAgent.ExecuteNonQuery(
				ConfigurationManager.ConnectionStrings[VWebConfigurationReader.ConnectionStringName].ConnectionString,
				CommandType.StoredProcedure,
				"VWeb_Tag_DeleteAllByComponentID",
				out returnValue,
				new SqlParameter("@ApplicationName", VWebConfigurationReader.ApplicationName),
				new SqlParameter("@ComponentID", componentID)
			);

			switch ((Int32)returnValue)
			{
				case 0:
					return TagRemoveAllResult.Success;
				default:
					return TagRemoveAllResult.Failure;
			}
		}

		public static TagRemoveAllResult RemoveAll(String componentID, String relationID)
		{
			if (componentID == null)
				throw new ArgumentNullException("componentID");

			if (relationID == null)
				throw new ArgumentNullException("relationID");

			if (String.IsNullOrEmpty(componentID))
				throw new ArgumentOutOfRangeException("componentID");

			if (String.IsNullOrEmpty(relationID))
				throw new ArgumentOutOfRangeException("relationID");

			if (!VUtility.IsGuid(relationID))
				throw new FormatException("relationID must Guid.");

			Object returnValue = null;

			SqlClientAgent.ExecuteNonQuery(
				ConfigurationManager.ConnectionStrings[VWebConfigurationReader.ConnectionStringName].ConnectionString,
				CommandType.StoredProcedure,
				"VWeb_Tag_DeleteAllByRelationID",
				out returnValue,
				new SqlParameter("@ApplicationName", VWebConfigurationReader.ApplicationName),
				new SqlParameter("@ComponentID", componentID),
				new SqlParameter("@RelationID", relationID)
			);

			switch ((Int32)returnValue)
			{
				case 0:
					return TagRemoveAllResult.Success;
				default:
					return TagRemoveAllResult.Failure;
			}
		}

		private static Tag fillTag(SqlDataReader reader)
		{
			return new Tag(
				reader["TagName"].ToString(),
				(Int32) reader["Count"]);
		}

		public static TagCollection GetAllTagCollection()
		{
			SqlDataReader reader = SqlClientAgent.ExecuteReader(
				ConfigurationManager.ConnectionStrings[VWebConfigurationReader.ConnectionStringName].ConnectionString,
				CommandType.StoredProcedure,
				"VWeb_Tag_GetAllTags",
				new SqlParameter("@ApplicationName", VWebConfigurationReader.ApplicationName)
			);

			TagCollection tags = null;

			try
			{
				if (reader.HasRows)
				{
					tags = new TagCollection();

					while (reader.Read())
					{
						tags.Add(fillTag(reader));
					}
				}
			}
			finally
			{
				reader.Close();
			}

			return tags;
		}

		public static TagCollection GetTagCollection(String componentID)
		{
			if (componentID == null)
				throw new ArgumentNullException("componentID");

			if (String.IsNullOrEmpty(componentID))
				throw new ArgumentOutOfRangeException("componentID");

			SqlDataReader reader = SqlClientAgent.ExecuteReader(
				ConfigurationManager.ConnectionStrings[VWebConfigurationReader.ConnectionStringName].ConnectionString,
				CommandType.StoredProcedure,
				"VWeb_Tag_GetTagsByComponentID",
				new SqlParameter("@ApplicationName", VWebConfigurationReader.ApplicationName),
				new SqlParameter("@ComponentID", componentID)
			);

			TagCollection tags = null;

			try
			{
				if (reader.HasRows)
				{
					tags = new TagCollection();

					while (reader.Read())
					{
						tags.Add(fillTag(reader));
					}
				}
			}
			finally
			{
				reader.Close();
			}

			return tags;
		}

		public static TagCollection GetTagCollection(String componentID, String relationID)
		{
			if (componentID == null)
				throw new ArgumentNullException("componentID");

			if (relationID == null)
				throw new ArgumentNullException("relationID");

			if (String.IsNullOrEmpty(componentID))
				throw new ArgumentOutOfRangeException("componentID");

			if (String.IsNullOrEmpty(relationID))
				throw new ArgumentOutOfRangeException("relationID");

			if (!VUtility.IsGuid(relationID))
				throw new FormatException("relationID must Guid.");

			SqlDataReader reader = SqlClientAgent.ExecuteReader(
				ConfigurationManager.ConnectionStrings[VWebConfigurationReader.ConnectionStringName].ConnectionString,
				CommandType.StoredProcedure,
				"VWeb_Tag_GetTagsByRelationID",
				new SqlParameter("@ApplicationName", VWebConfigurationReader.ApplicationName),
				new SqlParameter("@ComponentID", componentID),
				new SqlParameter("@RelationID", relationID)
			);

			TagCollection tags = null;

			try
			{
				if (reader.HasRows)
				{
					tags = new TagCollection();

					while (reader.Read())
					{
						tags.Add(fillTag(reader));
					}
				}
			}
			finally
			{
				reader.Close();
			}

			return tags;
		}
	}

	public class TagCollection : Collection<Tag> { }
}
